package club.westudy.distributed.lock.internal.redis;

import club.westudy.distributed.lock.DistributedLockService;
import club.westudy.distributed.lock.internal.InternalLockExecutorService;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;

import java.util.concurrent.TimeUnit;

public class RedisInternalLockExecutorService implements InternalLockExecutorService {
    RedissonClient redissonClient;

    @Override
    public void initial(long guardScanTimeMs) {
        //1.初始化注册表
        //2.初始化Redis连接池
        Config config = new Config();
        config.useSingleServer().setPassword("1234")
                // use "rediss://" for SSL connection
                .setAddress("redis://192.168.0.110:9736");
        redissonClient = Redisson.create(config);
    }

    @Override
    public void destroy() {
        //1.对注册表中未解锁的锁进行释放
        //2.对Redis连接池进行释放
        redissonClient.shutdown();
    }

    @Override
    public DistributedLockService.CriticalRegionContext acquire(String feature, long maxLeaseTimeMs, long tryLockWaitTimeMs) throws InterruptedException {
        // 1.构建Redis分布式锁
        RLock lock = redissonClient.getLock(feature);
        // 2.将锁向注册表注册，并与锁特征字符串绑定
        // 3.将锁特征字符串 写入临界区上下文
        DistributedLockService.CriticalRegionContext criticalRegionContext = null;
        // 4.进行加锁
        if (!lock.tryLock(tryLockWaitTimeMs, maxLeaseTimeMs, TimeUnit.MILLISECONDS)) {
            criticalRegionContext.setLocked(false);
            return criticalRegionContext;
        }
        criticalRegionContext.setLocked(true);
        // 5.返回临界区上下文
        return criticalRegionContext;
    }

    @Override
    public void release(DistributedLockService.CriticalRegionContext criticalRegionContext) {
        // 1.从临界区上下文获取锁特征字符串
        String lockFeature = criticalRegionContext.getLockFeature();
        // 2.从注册表根据锁特征字符串获取分布式锁
        RLock lock = redissonClient.getLock(lockFeature);
        // 3.进行解锁操作
        lock.unlock();
        // 4.进行上下文销毁
    }
}
